package com.tools.common.security.secret;

import com.tools.common.io.CharsetEnum;
import com.tools.common.object.Note;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.security.KeyPair;

/**
 * SM2 非对称加密算法的管理实例
 * */
@Note("SM2 非对称加密算法的管理实例")
public final class SM2Cypher implements Cypher {

    @Note("加密的公钥")
    private final BCECPublicKey publicKey;

    @Note("解密的公钥")
    private final BCECPrivateKey privateKey;

    /* **************************************************************************************
     *
     *          构造器
     *
     * **************************************************************************************
     * */

    public SM2Cypher() {
        KeyPair keyPair = SecretKit.createSM2KeyPair();
        this.publicKey = (BCECPublicKey) keyPair.getPublic();
        this.privateKey = (BCECPrivateKey) keyPair.getPrivate();
    }

    public SM2Cypher(KeyPair keyPair) {
        private_checkKeyPair(keyPair);
        this.publicKey = (BCECPublicKey) keyPair.getPublic();
        this.privateKey = (BCECPrivateKey) keyPair.getPrivate();
    }

    public SM2Cypher(BCECPublicKey publicKey, BCECPrivateKey privateKey) {
        private_checkKeyPair(publicKey, privateKey);
        this.publicKey = publicKey;
        this.privateKey = privateKey;
    }

    public SM2Cypher(String publicKey, String privateKey) {
        private_checkKeyPair(publicKey, privateKey);
        this.publicKey = SecretKit.toSM2PublicKey(new BouncyCastleProvider(), publicKey);
        this.privateKey = SecretKit.toSM2PrivateKey(new BouncyCastleProvider(), privateKey);
    }

    public BCECPublicKey getPublicKey() {
        return publicKey;
    }

    public BCECPrivateKey getPrivateKey() {
        return privateKey;
    }


    /* **************************************************************************************
     *
     *          实现方法
     *
     * **************************************************************************************
     * */

    @Override
    public String encrypt(String plaintext) {
        return SecretKit.encryptWithSM2(plaintext, this.publicKey);
    }

    @Override
    public String decrypt(String ciphertext) {
        return SecretKit.decryptWithSM2(ciphertext, this.privateKey);
    }

    @Override
    public String encrypt(String plaintext, CharsetEnum charset) {
        return SecretKit.encryptWithSM2(plaintext, this.publicKey);
    }

    @Override
    public String decrypt(String ciphertext, CharsetEnum charset) {
        return SecretKit.decryptWithSM2(ciphertext, this.privateKey);
    }

    /* **************************************************************************************
     *
     *          私有逻辑
     *
     * **************************************************************************************
     * */


    @Note("校验密钥对")
    private void private_checkKeyPair(KeyPair keyPair) {
        if(keyPair == null) throw new NullPointerException("SM2 非对称加密所需密钥对实例不能为 null");
    }

    @Note("校验密钥对")
    private void private_checkKeyPair(BCECPublicKey publicKey, BCECPrivateKey privateKey) {
        if(publicKey == null) throw new NullPointerException("SM2 非对称加密所需公钥不能为 null");
        if(privateKey == null) throw new NullPointerException("SM2 非对称加密所需私钥不能为 null");
    }

    @Note("校验密钥对")
    private void private_checkKeyPair(String publicKey, String privateKey) {
        if(publicKey == null) throw new NullPointerException("SM2 非对称加密所需公钥不能为空");
        if(privateKey == null) throw new NullPointerException("SM2 非对称加密所需私钥不能为空");
    }

}
